1 /*
2 * Angkor Web Framework
3 *
4 * Distributable under LGPL license.
5 * See terms of license at gnu.org.
6 */
7
8 package com.tirsen.angkor.beans;
9
10 import com.tirsen.angkor.Debug;
11 import org.apache.log4j.Category;
12
13 import java.beans.IndexedPropertyDescriptor;
14 import java.beans.IntrospectionException;
15 import java.beans.Introspector;
16 import java.beans.PropertyDescriptor;
17 import java.beans.PropertyEditor;
18 import java.beans.PropertyEditorManager;
19 import java.lang.reflect.Array;
20 import java.lang.reflect.InvocationTargetException;
21 import java.util.AbstractList;
22 import java.util.Collection;
23 import java.util.Iterator;
24 import java.util.List;
25
26 /***
27 *
28 * <!-- $Id: PropertySupport.java,v 1.2 2002/10/09 21:37:37 tirsen Exp $ -->
29 *
30 * @author $Author: tirsen $
31 * @version $Revision: 1.2 $
32 */
33 class PropertySupport
34 {
35 private static final Category logger = Debug.getCategory();
36
37 private BeanModel beanModel;
38 private PropertyDescriptor property;
39 private Class propertyClass;
40
41 public PropertySupport(BeanModel proxy, String property, Class propertyClass)
42 {
43 this.beanModel = proxy;
44 this.propertyClass = propertyClass;
45 this.property = findPropertyDescriptor(proxy.getObjectClass(), property);
46 }
47
48 private static PropertyDescriptor findPropertyDescriptor(Class klass, String property)
49 {
50 PropertyDescriptor[] properties;
51 try
52 {
53 properties = Introspector.getBeanInfo(klass).getPropertyDescriptors();
54 }
55 catch (IntrospectionException e)
56 {
57 throw new RuntimeException(e.getMessage());
58 }
59
60 PropertyDescriptor propertyDesc = null;
61 for (int i = 0; i < properties.length; i++)
62 {
63 if (properties[i].getName().equals(property))
64 {
65 propertyDesc = properties[i];
66 break;
67 }
68 }
69 if (propertyDesc == null) throw new RuntimeException("No property " + property + " in bean of type " + klass.getName());
70
71 return propertyDesc;
72 }
73
74 Object getBean()
75 {
76 return beanModel.getBean();
77 }
78
79 public Object getValue()
80 {
81 Object bean = getBean();
82 try
83 {
84 System.out.println("getPropertyDescriptor().getReadMethod() = " + getPropertyDescriptor().getReadMethod());
85 System.out.println("bean = " + bean);
86 return getPropertyDescriptor().getReadMethod().invoke(bean, null);
87 }
88 catch (IllegalAccessException e)
89 {
90 throw new IllegalAccessError(e.getMessage());
91 }
92 catch (InvocationTargetException e)
93 {
94 // handle this better?
95 throw new RuntimeException(e.getMessage());
96 }
97 }
98
99 public boolean isReadOnly()
100 {
101 return property.getWriteMethod() == null || getPropertyEditor() == null;
102 }
103
104 public void setValue(Object value)
105 {
106 if (isReadOnly()) throw new IllegalStateException("Trying to update a read-only property.");
107 try
108 {
109 property.getWriteMethod().invoke(getBean(), new Object[]{value});
110 }
111 catch (IllegalAccessException e)
112 {
113 throw new IllegalAccessError("Could not access property \"" + property.getName() + "\"." +
114 "Note: If you are using inner classes as models they need to be public.");
115 }
116 catch (InvocationTargetException e)
117 {
118 // handle this better?
119 throw new RuntimeException(e.getMessage());
120 }
121 }
122
123 public PropertyEditor getPropertyEditor()
124 {
125 PropertyEditor editor = null;
126
127 Class editorClass = property.getPropertyEditorClass();
128 if (editorClass != null)
129 {
130 try
131 {
132 editor = (PropertyEditor) editorClass.newInstance();
133 }
134 catch (InstantiationException ignore)
135 {
136 }
137 catch (IllegalAccessException ignore)
138 {
139 }
140 }
141
142 if (editor == null)
143 {
144 editor = PropertyEditorManager.findEditor(getPropertyDescriptor().getPropertyType());
145 }
146
147 return editor;
148 }
149
150 public PropertyDescriptor getPropertyDescriptor()
151 {
152 return property;
153 }
154
155 private class MultiValueList extends AbstractList
156 {
157 public Object get(int index)
158 {
159 return getValue(index);
160 }
161
162 public int size()
163 {
164 return PropertySupport.this.size();
165 }
166 }
167
168 public List getList()
169 {
170 return new MultiValueList();
171 }
172
173 public Object getValue(int index)
174 {
175 PropertyDescriptor property = getPropertyDescriptor();
176 if (property instanceof IndexedPropertyDescriptor) return indexedGetValue(index);
177 Class type = property.getPropertyType();
178 Object value;
179 if (type.isArray())
180 {
181 value = Array.get(getValue(), index);
182 }
183 else if (List.class.isAssignableFrom(type))
184 {
185 List list = (List) getValue();
186 value = list.get(index);
187 }
188 else if (Iterator.class.isAssignableFrom(type))
189 {
190 Iterator iterator = (Iterator) getValue();
191 value = getComponentFromIterator(iterator, index);
192 }
193 else if (Collection.class.isAssignableFrom(type))
194 {
195 Collection collection = (Collection) getValue();
196 Iterator iterator = collection.iterator();
197 value = getComponentFromIterator(iterator, index);
198 }
199 else
200 {
201 throw new IllegalStateException("Unsupported type of multi-valued property: " + type.getName());
202 }
203 return value;
204 }
205
206 private Object getComponentFromIterator(Iterator iterator, int index)
207 {
208 Object value;
209 value = null;
210 int currentIndex = 0;
211 while (currentIndex <= index)
212 {
213 value = iterator.next();
214 currentIndex++;
215 }
216 if (value == null) throw new IndexOutOfBoundsException("Property " + getPropertyDescriptor().getName() + " does not have value at index " + index);
217 return value;
218 }
219
220 public Object indexedGetValue(int index)
221 {
222 Object bean = getBean();
223 try
224 {
225 System.out.println("getPropertyDescriptor().getReadMethod() = " + getPropertyDescriptor().getReadMethod());
226 System.out.println("bean = " + bean);
227 IndexedPropertyDescriptor property = (IndexedPropertyDescriptor) getPropertyDescriptor();
228 return property.getIndexedReadMethod().invoke(bean, new Object[]{new Integer(index)});
229 }
230 catch (IllegalAccessException e)
231 {
232 throw new IllegalAccessError(e.getMessage());
233 }
234 catch (InvocationTargetException e)
235 {
236 if (e.getTargetException() instanceof RuntimeException)
237 {
238 throw (RuntimeException) e.getTargetException();
239 }
240 if (e.getTargetException() instanceof Error)
241 {
242 throw (Error) e.getTargetException();
243 }
244 throw new RuntimeException(e.getMessage());
245 }
246 }
247
248 private int indexedSize()
249 {
250 IndexedPropertyDescriptor descriptor = (IndexedPropertyDescriptor) getPropertyDescriptor();
251 int size = 0;
252 try
253 {
254 while (size < Integer.MAX_VALUE)
255 {
256 indexedGetValue(size);
257 size++;
258 }
259 }
260 catch (IndexOutOfBoundsException expected)
261 {
262 }
263 return size;
264 }
265
266 public int size()
267 {
268 PropertyDescriptor property = getPropertyDescriptor();
269 if (property instanceof IndexedPropertyDescriptor) return indexedSize();
270 Class type = property.getPropertyType();
271 int size;
272 if (type.isArray())
273 {
274 Object value = getValue();
275 if (value == null)
276 return 0;
277 else
278 size = Array.getLength(value);
279 }
280 else if (Collection.class.isAssignableFrom(type))
281 {
282 Collection collection = (Collection) getValue();
283 size = collection.size();
284 }
285 else if (Iterator.class.isAssignableFrom(type))
286 {
287 Iterator iterator = (Iterator) getValue();
288 size = 0;
289 while (iterator.hasNext())
290 {
291 iterator.next();
292 size++;
293 }
294 }
295 else
296 {
297 throw new IllegalStateException("Unsupported type of multi-valued property: " + type.getName());
298 }
299 return size;
300 }
301
302 public Class getComponentType()
303 {
304 Class type;
305 if (propertyClass != null)
306 {
307 type = propertyClass;
308 }
309 else
310 {
311 type = getPropertyDescriptor().getPropertyType();
312 if (type.isArray())
313 {
314 type = type.getComponentType();
315 }
316 else if (type == List.class)
317 {
318 throw new RuntimeException("Could not determine component type of " + property + " with type " + type + "." +
319 "You have to specify it manually.");
320 }
321 }
322 return type;
323 }
324 }
This page was automatically generated by Maven